/*
 * Config.cpp
 *
 *  Created on: 7 июн. 2022 г.
 *      Author: nikita
 */

#include "Config.h"

namespace STC_calc
{

std::list<std::shared_ptr<CurrentOptions>> Config::options_list;
std::shared_ptr<CurrentOptions> Config::current;
std::string Config::program_location;

void Config::next_configs(const CurrentOptions::Modes mode, const std::string& execution_str, const string_vector& flags_up)
{
    std::shared_ptr<CurrentOptions> next = std::make_shared<CurrentOptions>(mode, execution_str, flags_up);
	next_configs(next);
}

void Config::next_configs(const std::shared_ptr<CurrentOptions> confs)
{
	bool empty = options_list.empty();
	options_list.push_back(confs);

	if (empty)
	{
		current = *options_list.begin();
		return;
	}
	current = *options_list.end();
}

void Config::back_configs()
{
	options_list.pop_back();
	if (options_list.empty()) return;
	current = options_list.back();
}

void Config::add_variable(const string_list& args)
{
    current->add_variable(args);
}
void Config::add_variable(const std::shared_ptr<MVariable> var)
{
    current->add_variable(var);
}
void Config::add_variable(const std::string& name, const long double min, const long double max, const long double steps)
{
	current->add_variable(name, min, max, steps);
}

void Config::add_constant(const string_list& args)
{
    current->add_constant(args);
}
void Config::add_constant(const std::shared_ptr<MConstant> var)
{
    current->add_constant(var);
}
void Config::add_constant(const std::string& name, const long double value)
{
    current->add_constant(name, value);
}

std::shared_ptr<MVariable> Config::get_variable(const std::string& name)
{
    auto answer = current->get_variable(name);
    if (answer.second) return answer.first;
    std::list<std::shared_ptr<CurrentOptions>>::iterator iterator = options_list.end();

    while (iterator != options_list.begin())
    {
        --iterator;
        answer = (*iterator)->get_variable(name);
        if (answer.second) return answer.first;
    }
    throw(RuntimeErrorClass("Non-existing operation: " + name));
}
std::shared_ptr<MConstant> Config::get_constant(const std::string& name)
{
    auto answer = current->get_constant(name);
    if (answer.second) return answer.first;
    std::list<std::shared_ptr<CurrentOptions>>::iterator iterator = options_list.end();

    while (iterator != options_list.begin())
    {
        --iterator;
        answer = (*iterator)->get_constant(name);
        if (answer.second) return answer.first;
    }
    throw(RuntimeErrorClass("Non-existing operation: " + name));
}

bool Config::is_var(const std::string& name)
{
    auto answer = current->is_var(name);
    if (answer) return true;
    std::list<std::shared_ptr<CurrentOptions>>::iterator iterator = options_list.end();

    while (iterator != options_list.begin())
    {
        --iterator;
        answer = (*iterator)->is_var(name);
        if (answer) return true;
    }
    return false;
}
bool Config::is_const(const std::string& name)
{
    auto answer = current->is_const(name);
    if (answer) return true;
    std::list<std::shared_ptr<CurrentOptions>>::iterator iterator = options_list.end();

    while (iterator != options_list.begin())
    {
        --iterator;
        answer = (*iterator)->is_const(name);
        if (answer) return true;
    }
    return false;
}

void Config::set_mode(const Modes mode)
{
    current->set_mode(mode);
}

void Config::set_location(const std::string& args)
{
	program_location = args;
}
bool Config::is_flag(const std::string& flag_name)
{
	return current->get_flag(flag_name);
}
void Config::add_flag(const std::string& flag_name)
{
    current->set_flag(flag_name);
}

} /* namespace STC_calc */
